package com.person.mall.service.Impl;

import com.google.gson.Gson;
import com.person.mall.dao.ProductMapper;
import com.person.mall.enums.ProductDetailEnum;
import com.person.mall.enums.ResponseEnum;
import com.person.mall.form.CartAddForm;
import com.person.mall.form.CartUpdateForm;
import com.person.mall.pojo.Cart;
import com.person.mall.pojo.Product;
import com.person.mall.service.ICartService;
import com.person.mall.vo.CartProductVo;
import com.person.mall.vo.CartVo;
import com.person.mall.vo.ResponseVo;
import com.sun.org.apache.bcel.internal.generic.NEW;
import io.netty.util.internal.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.xml.crypto.Data;
import java.math.BigDecimal;
import java.util.*;

import static com.person.mall.enums.ResponseEnum.PRODUCT_OFF_ERROR;

/**
 * @author 最酷的桃儿wjc
 * * @date 2022/5/19
 */
@Service
public class CartServiceImpl implements ICartService {

    private static final String CART_REDIS_KEY_TEMPLATE = "cart_%d";

    @Autowired
    private ProductMapper productMapper;
    //Spring封装好的一个类
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    private  Gson gson = new Gson();


    @Override
    public ResponseVo<CartVo> addCart(Integer uid,CartAddForm cartAddForm) {
        Product product = productMapper.selectByPrimaryKey(cartAddForm.getProductId());

        //不重要，都是一些校验
        if (product == null){
            return ResponseVo.error(PRODUCT_OFF_ERROR);
        }
        if (!product.getStatus().equals(ProductDetailEnum.ON_SALE.getCode())){
            return ResponseVo.error(PRODUCT_OFF_ERROR);
        }

        //建一个redis中hashMap
        HashOperations<String, String, String> opsForHash = stringRedisTemplate.opsForHash();
        Cart cart;
        //rediskey
        String redisKey = String.format(CART_REDIS_KEY_TEMPLATE, uid);
        //根据rediskey，以及mapkey取值
        String opsForHashValue = opsForHash.get(redisKey, String.valueOf(product.getId()));
        //如果为空新建一个cart对象，如果存在就给数量+1
        if (StringUtils.isEmpty(opsForHashValue)){
            cart = new Cart(product.getId(), 1, cartAddForm.getSelected());
        } else {
            cart = gson.fromJson(opsForHashValue, Cart.class);
            cart.setQuantity(cart.getQuantity()+1);
        }
//        最后写入redis数据库
        opsForHash.put(redisKey,String.valueOf(product.getId()),gson.toJson(cart));

        return cartList(uid);
    }

    @Override
    public ResponseVo<CartVo> cartList(Integer uid) {
//        获取购物车当中所有的信息
        HashOperations<String, String, String> opsHashValue = stringRedisTemplate.opsForHash();
        String redisKey = String.format(CART_REDIS_KEY_TEMPLATE,uid);
        Map<String, String> entries = opsHashValue.entries(redisKey);

        CartVo cartVo = new CartVo();
        List<CartProductVo> cartProductVoList = new ArrayList<>();
        Set<Integer> productIdSet = new HashSet<>();
        BigDecimal totalPrice = BigDecimal.ZERO;
        boolean selectAll = true;
        Integer cartTotalQuantity = 0;

//        遍历购物车信息
        for (Map.Entry<String, String> entry : entries.entrySet()) {
            Integer productId = Integer.valueOf(entry.getKey());
            productIdSet.add(productId);

            Cart cart = gson.fromJson(entry.getValue(), Cart.class);
            //TODO 需要优化，将productId放到set集合中，在SQL使用In
            Product product = productMapper.selectByPrimaryKey(productId);
            if(product!=null){
                CartProductVo cartProductVo = new CartProductVo(
                        productId,
                        cart.getQuantity(),
                        product.getName(),
                        product.getSubtitle(),
                        product.getMainImage(),
                        product.getPrice(),
                        product.getStatus(),
                        product.getPrice().multiply(BigDecimal.valueOf(cart.getQuantity())),
                        product.getStock(),
                        cart.getProductSelected()
                        );
                cartProductVoList.add(cartProductVo);
                if (!cart.getProductSelected()){
                    selectAll = false;
                }
//               计算总价，如果商品被选中了就计算到总价当中
                if (cart.getProductSelected()) {
                    totalPrice = totalPrice.add(cartProductVo.getProductTotalPrice());
                }
            }
            cartTotalQuantity += cart.getQuantity();
        }
//        给cartVo设置产品列表结合
        cartVo.setCartProductVoList(cartProductVoList);
        cartVo.setSelectedAll(selectAll);
        cartVo.setCartTotalQuantity(cartTotalQuantity);
        cartVo.setCartTotalPrice(totalPrice);
        return ResponseVo.successGetData(cartVo);
    }

    @Override
    public ResponseVo<CartVo> update(Integer uid, Integer productId, CartUpdateForm cartUpdateForm) {
        HashOperations<String, String, String> opsHashValue = stringRedisTemplate.opsForHash();
        String redisKey = String.format(CART_REDIS_KEY_TEMPLATE,uid);

        String value = opsHashValue.get(redisKey, String.valueOf(productId));

        Cart cart = gson.fromJson(value, Cart.class);

        if (cartUpdateForm.getQuantity() != null){
            cart.setQuantity(cartUpdateForm.getQuantity());
        }

        if (cartUpdateForm.getSelected() != null){
            cart.setProductSelected(cartUpdateForm.getSelected());
        }

        opsHashValue.put(redisKey, String.valueOf(productId),gson.toJson(cart));

        return cartList(uid);
    }

    /**
     * 删除购物车 
     * @param uid
     * @param productId
     * @return
     */
    @Override
    public ResponseVo<CartVo> delete(Integer uid, Integer productId) {
        HashOperations<String, String, String> opsHashValue = stringRedisTemplate.opsForHash();
        String redisKey = String.format(CART_REDIS_KEY_TEMPLATE,uid);

        opsHashValue.delete(redisKey, String.valueOf(productId));
        return cartList(uid);
    }

    @Override
    public ResponseVo<Integer> sumData(Integer uid) {
        HashOperations<String, String, String> opsHashValue = stringRedisTemplate.opsForHash();
        String redisKey = String.format(CART_REDIS_KEY_TEMPLATE,uid);

        Map<String, String> entries = opsHashValue.entries(redisKey);

        Integer sumQuantity = 0;
        for (Map.Entry<String, String> entry : entries.entrySet()) {
            Cart cart = gson.fromJson(entry.getValue(), Cart.class);
            sumQuantity += cart.getQuantity();
        }

        return ResponseVo.successGetData(sumQuantity);
    }

    @Override
    public ResponseVo<CartVo> selectAll(Integer uid) {
        HashOperations<String, String, String> opsHashValue = stringRedisTemplate.opsForHash();
        String redisKey = String.format(CART_REDIS_KEY_TEMPLATE,uid);

        List<Cart> carts = cartListForSelect(uid);
        for (Cart cart : carts) {
            cart.setProductSelected(true);
            opsHashValue.put(redisKey, String.valueOf(cart.getProductId()),gson.toJson(cart));
        }

        return cartList(uid);
    }

    @Override
    public ResponseVo<CartVo> unselectAll(Integer uid) {
        HashOperations<String, String, String> opsHashValue = stringRedisTemplate.opsForHash();
        String redisKey = String.format(CART_REDIS_KEY_TEMPLATE,uid);

        List<Cart> carts = cartListForSelect(uid);
        for (Cart cart : carts) {
            cart.setProductSelected(false);
            opsHashValue.put(redisKey, String.valueOf(cart.getProductId()),gson.toJson(cart));
        }

        return cartList(uid);
    }

    public List<Cart> cartListForSelect(Integer uid){
        HashOperations<String, String, String> opsHashValue = stringRedisTemplate.opsForHash();
        String redisKey = String.format(CART_REDIS_KEY_TEMPLATE,uid);

        List<Cart> cartList = new ArrayList<>();
        Map<String, String> entries = opsHashValue.entries(redisKey);
        for (Map.Entry<String, String> entry : entries.entrySet()) {
            Cart cart = gson.fromJson(entry.getValue(), Cart.class);
            cartList.add(cart);
        }
        return cartList;
    }
}
